/*=============================================================================
*
*   Copyright (C) 2020 All rights reserved.
*
*   Filename:		solid.hpp
*
*   Author: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Date: 2020-03-04 17:57
*
*   Last Editors: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Last modified:	2020-08-04 01:25
*
*   Description:
*
=============================================================================*/
#ifndef SOLID_H
#define SOLID_H

#include "geometry/shape/nodal_dof.hpp"
#include "io/vtu_writer.hpp"
#include "model/couple/displacement.hpp"
#include "model/solve/assemble_elemental_mat.hpp"

namespace geoxfem {

namespace model {
struct solid {};
}  // namespace model

namespace traits {
template <>
struct if_consider_deform<model::solid> {
  static constexpr bool value = true;
};
}  // namespace traits

namespace geometry {

template <>
template <typename Vertex>
std::vector<model::Dof*> get_nodal_dofs<model::solid> /*{{{*/
  ::apply(Vertex& vertex) {
  return get_nodal_dofs<model::displacement>::apply(vertex);
} /*}}}*/

template <>
template <typename Vertex>
void set_nodal_dofs<model::solid>::apply(Vertex& v) { /*{{{*/
  set_nodal_dofs<model::displacement>::apply(v);
  return;
} /*}}}*/

template <>
template <typename DimensionType, typename degree>
std::vector<model::Dof*> get_elemental_dof<model::solid>::/*{{{*/
  apply(const geometry::ShapeInterface<DimensionType, degree>& shp) {
  return get_elemental_dof<model::displacement>::apply(shp);
} /*}}}*/

}  // namespace geometry
namespace model {

template <>
template <typename DimensionType, typename degree, typename TimeStep>
MatrixXR assemble_elemental_kay<solid>::/*{{{*/
  apply(const geometry::ShapeInterface<DimensionType, degree>& shp,
        const TimeStep&) {
  return assemble_sub_kay<displacement, displacement>::apply(shp);
} /*}}}*/

template <>
template <typename DimensionType, typename degree, typename TimeStep>
VectorXR assemble_element_rhs_for_tstep<solid>::/*{{{*/
  apply(const geometry::ShapeInterface<DimensionType, degree>& shp,
        const TimeStep&) {
  return assemble_sub_rhs_for_tstep<displacement, displacement>::apply(shp);
} /*}}}*/

template <>
template <typename DimensionType, typename degree, typename TimeStep>
VectorXR assemble_element_rhs_for_iter<solid>::/*{{{*/
  apply(const geometry::ShapeInterface<DimensionType, degree>& shp,
        const TimeStep&) {
  return assemble_sub_rhs_for_iter<displacement, displacement>::apply(shp);
} /*}}}*/

}  // namespace model

namespace io {

template <>
template <typename Mesh>
void write_ptree<model::solid>::/*{{{*/
  apply(const Mesh& mesh, boost::property_tree::ptree& root) {
  using ptree      = boost::property_tree::ptree;
  ptree& PointData = root.get_child("VTKFile.UnstructuredGrid.Piece.PointData");
  ptree& CellData  = root.get_child("VTKFile.UnstructuredGrid.Piece.CellData");
  ////////////////////////////////////////////////////////////////
  // populate point data
  ptree deform = io::vtu_node_info::apply(mesh, io::vtu_vertex_deform{},
                                          {{"type", "Float32"},
                                           {"NumberOfComponents", "3"},
                                           {"Name", "displacement"}});
  PointData.add_child("DataArray", deform);
  ptree v_xfem = io::vtu_node_info::apply(
    mesh, [](const auto& v) { return v.ifXfem() ? "1\n" : "0\n"; },
    {{"type", "Float32"}, {"Name", "v_xfem"}});
  PointData.add_child("DataArray", v_xfem);
  ////////////////////////////////////////////////////////////////
  // populate cell data

  ptree sigma = io::vtu_cell_info::apply(
    mesh, io::vtu_cell_sigma{},
    {{"type", "Float32"}, {"NumberOfComponents", "9"}, {"Name", "sigma"}});
  CellData.add_child("DataArray", sigma);

  ptree epsilon = io::vtu_cell_info::apply(
    mesh, io::vtu_cell_epsilon{},
    {{"type", "Float32"}, {"NumberOfComponents", "9"}, {"Name", "epsilon"}});
  CellData.add_child("DataArray", epsilon);

  ptree cell_xfem = io::vtu_node_info::apply(
    mesh, [](const auto& v) { return v.ifXfem() ? "1\n" : "0\n"; },
    {{"type", "Float32"}, {"Name", "cell_xfem"}});
  PointData.add_child("DataArray", cell_xfem);
  return;
} /*}}}*/

}  // namespace io
}  // namespace geoxfem

#endif /* SOLID_H */
